package com.hzj.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.hzj.exception.HospitalException;
import com.hzj.helper.HttpRequestHelper;
import com.hzj.pojo.HospitalSet;
import com.hzj.pojo.OrderInfo;
import com.hzj.pojo.PaymentInfo;
import com.hzj.pojo.RefundInfo;
import com.hzj.service.HospitalService;
import com.hzj.service.OrderInfoService;
import com.hzj.utils.AlipayConfig;
import com.hzj.utils.OrderUtils;
import com.hzj.utils.Result;
import com.hzj.utils.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Controller
@RequestMapping("/platformapi/order/zfb/auth")
public class ZfbController {


    @Autowired
    OrderInfoService ois;
    @Autowired
    HospitalService hs;

    private OrderInfo orderInfo;

    private PaymentInfo paymentInfo;

//    @PostMapping("/createNative/{orderId}")
//    public Result createNative(@PathVariable Integer orderId) {
//        if (StringUtils.isEmpty(orderId)) {
//            throw new HospitalException(ResultCodeEnum.PARAM_ERROR);
//        }
//
//
//        return Result.ok();
//    }


    /**
     * goAlipay方法的订单金额，订单名称等参数，直接复制放入方法入参就行了
     *
     * @RequestParam("orderNo") String orderNo, @RequestParam("totalPrice") String totalPrice,
     * @RequestParam("itemString") String itemString,
     */
//前往支付宝沙箱网关进行支付
    @ResponseBody
    @RequestMapping(value = "/createNative/{orderId}", produces = "text/html; charset=UTF-8")
    public String goAlipay(HttpServletRequest request,
                           HttpServletResponse response, @PathVariable Integer orderId) throws Exception {
        orderInfo = ois.queryById(Long.valueOf(orderId));

//实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
//设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.RETURN_URL);//同步
        alipayRequest.setNotifyUrl(AlipayConfig.NOTIFY_URL);//异步，必须为外网可以访问的网址
//OrderUtils.getOrderCode(new Random(5).nextInt(100))
//        orderInfo.getOutTradeNo()
        String out_trade_no = orderInfo.getOutTradeNo(); //订单号
        String total_amount = String.valueOf(orderInfo.getAmount());//付款金额，必填
        String subject = orderInfo.getDepname() + "|" + orderInfo.getTitle(); //订单名称，必填
        String body = orderInfo.getHosname() + "|" + orderInfo.getDepname() + "|" + orderInfo.getTitle() + "金额为：" + orderInfo.getAmount();//商品描述，可空
// 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "30m";
        if (null != total_amount) { //支付金额不等于空，并且订单名称不为空
            alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                    + "\"total_amount\":\"" + total_amount + "\","
                    + "\"subject\":\"" + subject + "\","
                    + "\"body\":\"" + body + "\","
                    + "\"timeout_express\":\"" + timeout_express + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//请求
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            System.out.println("========>" + result);
            return result;
        }
        return "失败";
    }

    //支付宝同步通知页面,成功返回
    @RequestMapping(value = "/alipayReturnNotice")
    public String alipayReturnNotice(HttpServletRequest request, HttpServletRequest response, HttpSession httpSession) throws Exception {
        log.info("支付成功, 进入同步通知接口...");
        orderInfo.setOrderStatus(1);

        ois.updateOrderByHosRecordId(orderInfo);
//获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
// log.info("同步：map集合中的nema：" + values);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
//乱码解决，这段代码在出现乱码时使用
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        log.info("支付宝返回参数：" + params);
// 调用SDK验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE);
        if (signVerified) {
            log.info("---验证通过---");
//商户订单号
            String orderNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//付款金额
            Double total_amount = Double.valueOf(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));

//          存入支付信息
            paymentInfo = new PaymentInfo();
            paymentInfo.setOutTradeNo(orderNo);//对外业务编号
            paymentInfo.setOrderId(orderInfo.getId());//订单id
            paymentInfo.setPaymentType(false);//微信(true)还是支付宝(false)
            paymentInfo.setTradeNo(trade_no);//交易编号
            paymentInfo.setTotalAmount(BigDecimal.valueOf(total_amount));//付款金额
            paymentInfo.setSubject(orderInfo.getHosname() + "挂号：" + orderInfo.getDepname() + "|" + orderInfo.getTitle());
            paymentInfo.setPaymentStatus(1);


            ois.updatePaymentInfo(paymentInfo);

            //添加订单号
            orderInfo.setOutTradeNo(orderNo);
            ois.updateOrderByHosRecordId(orderInfo);

            HospitalSet hospitalSet = hs.getHospitalSetByHoscode(orderInfo.getHoscode());

            //支付成功更新医院支付状态
            Map paramMap = new HashMap();
            paramMap.put("hosRecordId", orderInfo.getId());
            paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
            String sign = HttpRequestHelper.getSign(paramMap, hospitalSet.getSignKey());
            paramMap.put("sign", sign);
//            System.out.println("------" + hospitalSet.getApiUrl() + "/order/submitOrder");
            //请求医院系统接口
            JSONObject result = HttpRequestHelper.sendRequest(paramMap, hospitalSet.getApiUrl() + "/order/updatePayStatus");
            System.out.println("跟新支付状态返回数据==========>>" + result);
            if (result.getInteger("code") != 200) {
                throw new HospitalException(result.getString("message"), ResultCodeEnum.FAIL.getCode());
            }

        } else {
            log.error("同步回调签名验证失败");
        }
        return "redirect:http://localhost:3000/order/show?orderId=" + orderInfo.getId();
    }

    //支付宝异步 通知页面
    @RequestMapping(value = "/alipayNotifyNotice")
    public void alipayNotifyNotice(HttpServletRequest request, HttpServletRequest response, Map map) throws Exception {
        log.info("支付成功, 进入异步通知接口...");
//获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
// System.out.println("异步：map集合中的nema：" + values);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
//乱码解决，这段代码在出现乱码时使用
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
// 调用SDK验证签名
        log.info("支付宝返回参数：" + params);
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE);
        if (signVerified) {
//商户订单号
            String orderNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
//交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

        } else {
            log.error("异步回调签名验证失败");
        }
// return "success";
    }

    //退款
    @ResponseBody
    @RequestMapping("/Refund/{orderId}")
    public Result Refund(HttpServletResponse response, HttpSession session, @PathVariable Integer orderId) throws AlipayApiException {

        // 设置编码格式
        response.setContentType("text/html;charset=utf-8");

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
        //设置请求参数
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        //商户订单号，必填
        String out_trade_no = new String(orderInfo.getOutTradeNo());
        //需要退款的金额，该金额不能大于订单金额，必填
        String refund_amount = new String(String.valueOf(orderInfo.getAmount()));
        //标识一次退款请求，同一笔交易多次退款需要保证唯一。如需部分退款，则此参数必传；不传该参数则代表全额退款
        String out_request_no = new String(UUID.randomUUID().toString());
        // 字符转义很重要
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"refund_amount\":\"" + refund_amount + "\","
                + "\"out_request_no\":\"" + out_request_no + "\"}");
        //请求
        String result = alipayClient.execute(alipayRequest).getBody();
        //输出
        //以下写自己的订单退款代码
        log.info("返回结果={}", result);

        //生成退款订单
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setOutTradeNo(paymentInfo.getOutTradeNo());//对外业务编号
        refundInfo.setOrderId(orderInfo.getId());//订单id
        refundInfo.setPaymentType(2);//微信(true)还是支付宝(false)
        refundInfo.setTradeNo(paymentInfo.getTradeNo());//交易编号
        refundInfo.setTotalAmount(paymentInfo.getTotalAmount());//付款金额
        refundInfo.setSubject(orderInfo.getHosname() + "挂号：" + orderInfo.getDepname() + "|" + orderInfo.getTitle());
        refundInfo.setRefundStatus(1);
        ois.updateRefundInfo(refundInfo);


        return Result.ok(result);


    }

}
